#ifndef DRAM_SCHED_H_
#define DRAM_SCHED_H_

#include <list>
#include <map>
#include "simulator_sim.h"
#include "dram.h"

enum MemoryMode
{
  READ_MODE = 0,
  WRITE_MODE
};

class FrfcfsScheduler
{
public:
  FrfcfsScheduler(const MemoryConfig *config, Dram *dm);
  void add_req(DramReq *req);
  void data_collection(uint32_t bank);
  DramReq *schedule(uint32_t bank, uint32_t curr_row);
  void print(FILE *fp);
  uint32_t num_pending() const { return m_num_pending; }
  uint32_t num_write_pending() const { return m_num_write_pending; }

private:
  const MemoryConfig *m_config;
  Dram *m_dram;
  uint32_t m_num_pending;
  uint32_t m_num_write_pending;
  std::list<DramReq *> *m_queue;
  std::map<uint32_t, std::list<std::list<DramReq *>::iterator>> *m_bins;
  std::list<std::list<DramReq *>::iterator> **m_last_row;
  uint32_t *curr_row_service_time; // one set of variables for each bank.
  uint32_t *row_service_timestamp; // tracks when scheduler began servicing
                                   // current row

  std::list<DramReq *> *m_write_queue;
  std::map<uint32_t, std::list<std::list<DramReq *>::iterator>>
      *m_write_bins;
  std::list<std::list<DramReq *>::iterator> **m_last_write_row;

  MemoryMode m_mode;
};

#endif
